home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 1 Issue 2
/
PDCD-1 - Issue 02.iso
/
_utilities
/
utilities
/
003
/
_microcosm
/
!Microcosm
/
c
/
Microcosm
Wrap
Text File
|
1990-08-16
|
32KB
|
1,115 lines
/***************************************************************************
*
* Microcosm.c
*
* Archimedes
*
* Microcosm program - Public Domain release
* 5 June 1990 : version 1
*
* Written by....
* Michael Spearpoint
* 3 Lawrence Crescent
* Edgware
* Middx HA8 5PB
*
***************************************************************************/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include "res.h"
#include "resspr.h"
#include "bbc.h"
/**************************************************************************/
/* Define global variables and format of any functions */
#define VERSION "version 1 "
#define GRAPHICS TRUE /* Draw creature graphics code */
#define WRAP_AROUND FALSE /* Wrap around movement code */
/* Define screen plotting factors */
#define SCREEN_X 22 /* Screen plotting x factor */
#define SCREEN_Y 22 /* Screen plotting y factor */
#define ORIGIN_X 10 /* Origin of graph - x coordinate */
#define ORIGIN_Y 630 /* Origin of graph - y coordinate */
#define WIDTH 900 /* Graph width */
#define DIRECTIONS 8 /* Area to check for food etc - set to 8 or 4
* When 4 - checks n,e,s,w
* When 8 - checks n,ne,nw,e,w,s,se,sw */
#define X_MAX 55 /* Number of grid cells - x direction */
#define Y_MAX 27 /* Number of grid cells - y direction */
#define CREATURE_TYPES 10 /* Max number of creature types */
#define MAX_FOOD 4 /* Number of different creature types
* that a particular type can eat */
#define MAX_CREATURES (X_MAX * Y_MAX)
#define DEAD 0
#define EMPTY 0
#define FAIL -1
#define RANDOM(A) ((A + 1) * (float)rand() / (float)RAND_MAX)
/* Palette colours */
enum { WHITE, GREY1, GREY2, GREY3, GREY4, GREY5, GREY6, BLACK,
BLUE, YELLOW, GREEN, RED, CREAM, DARK_GREEN, ORANGE, CYAN };
/**************************************************************************/
/* Define procedures */
/* Initialisation procedures */
void initialise(void);
void create_populations(void);
void draw_axes(void);
/* File reading procedures */
BOOL load_file(void);
void read_data(int);
void read_general_data(void);
void read_initial_positions(void);
/* Main processing procedures */
void main_loop(void);
void process_creatures(void);
void update_graph(int);
/* Creature processing procedures */
void move_creature(int, int);
void consume_strength(int, int);
void feed(int, int);
void birth(int, int);
/* General routines */
BOOL valid_location(char, char);
int find_creature_at(char, char);
int find_free_creature(void);
/**************************************************************************/
char grid[X_MAX + 1][Y_MAX + 1] = EMPTY;
int pop_tots[CREATURE_TYPES + 1] = 0;
int old_pop_tots[CREATURE_TYPES + 1] = 0;
FILE *read;
sprite_area *sprite_bk;
/* Global data structure */
struct global
{
int iterations;
int wait;
BOOL random;
BOOL draw_creatures;
BOOL draw_overall;
int total_types;
float graph_scale;
} global = { 0, 0, TRUE, TRUE, TRUE, 1, (float) 1 };
/* Creature type structure */
struct type
{
char name[11]; /* Creature / sprite name */
int initial_number;/* Initial number for random start */
char move; /* Movement rate */
int max_str; /* Max strength for creature */
signed char consumption; /* Strength consumption per iteration */
int food; /* Valid food types for this creature type */
int food_value; /* Food value when creature is eaten */
int adult; /* Age at which creature can give birth */
int birth_str; /* Minimum strength for birth */
char child_str; /* Percentage of parents strength to child */
int decay; /* Creature type formed by the death of type */
}
type[CREATURE_TYPES];
/* Individual creature */
struct creature
{
char type; /* Creature type */
char x; /* x coord */
char y; /* y coord */
signed char dx; /* Movement in x dir +1,0,-1 */
signed char dy; /* Movement in y dir +1,0,-1 */
int str; /* Current strength */
char move_c; /* Movement counter */
int age; /* Age in iterations */
}
creature[MAX_CREATURES + 1] =
{
0, 0, 0, 0, 0, 0, 0, 0
};
#if DIRECTIONS == 8
struct loc_offset
{
signed char dx;
signed char dy;
}
loc_offset[DIRECTIONS] =
{ -1,-1, 0,-1, +1,-1, -1,0, +1,0, -1,+1, 0,+1, +1,+1 };
#endif
#if DIRECTIONS == 4
struct loc_offset
{
signed char dx;
signed char dy;
}
loc_offset[DIRECTIONS] =
{ 0,-1, -1,0, +1,0, 0,+1, };
#endif
/**************************************************************************/
/**************************************************************************/
/* INITIALISATION AND FILE READING PROCEDURES */
/**************************************************************************/
/* Initialise */
void initialise(void)
{
res_init("Microcosm"); /* Find resources */
resspr_init(); /* Find sprite file */
sprite_bk = resspr_area();
/* Set up screen mode and load palette */
bbc_mode(12);
system("<Microcosm$Dir>.Palette");
bbc_colour(128 + BLACK);
bbc_colour(WHITE);
bbc_cls();
/* Reseed randomiser */
srand(clock());
/* Start up message */
bbc_tab(22,8);
printf("Microcosm program (Public Domain)");
bbc_tab(26,10);
printf("%s",VERSION);
printf("%s",__DATE__);
bbc_tab(28,12);
printf("Michael Spearpoint");
bbc_tab(2,30);
printf("Press any key....");
bbc_get();
bbc_cls();
}
/**************************************************************************/
/* Load set up file */
BOOL load_file(void)
{
char *file = "<Microcosm$Dir>.SetUp";
BOOL comment = FALSE;
char chr;
int data_type;
read = fopen(file,"r");
/* Found file ? */
if (read == NULL)
{
printf("Error - SetUp file not found, program terminated");
return(FALSE);
}
/* Read file down to # character */
while ((chr = fgetc(read)) != '#')
{
switch (chr)
{
case '*' : comment = !comment;
break;
case '}' : if (comment == FALSE)
{ read_general_data(); }
break;
case '>' : if (comment == FALSE)
{
fscanf(read,"%i",&data_type);
read_data(data_type);
}
break;
default : break;
}
}
fclose(read);
return(TRUE);
}
/**************************************************************************/
/* Read general data from file */
void read_general_data(void)
{
static int count = 0;
char chr;
++count;
switch (count)
{
case 1 : fscanf(read,"%i", &global.total_types);
if (global.total_types > CREATURE_TYPES)
{
printf("Error - Too many creature types");
exit(NULL);
}
break;
case 2 : fscanf(read,"%i", &global.iterations);
break;
case 3 : do {
fscanf(read,"%c",&chr);
} while (chr == ' ');
global.random = (chr == 'Y') ? TRUE : FALSE;
read_initial_positions();
break;
case 4 : fscanf(read,"%i",&global.wait);
break;
case 5 : fscanf(read,"%f",&global.graph_scale);
break;
case 6 : do {
fscanf(read,"%c",&chr);
} while (chr == ' ');
global.draw_creatures = (chr == 'Y') ? TRUE : FALSE;
break;
case 7 : do {
fscanf(read,"%c",&chr);
} while (chr == ' ');
global.draw_overall = (chr == 'Y') ? TRUE : FALSE;
break;
default : break;
}
}
/**************************************************************************/
/* Read the initial creature positions from the setup file */
void read_initial_positions(void)
{
int x = -4, y = Y_MAX;
int c_type;
char chr;
/* Random creature set up ? */
if (global.random == TRUE)
{
/* Search file for next '}' character */
while ((chr = fgetc(read)) != '}') { }
ungetc('}',read);
}
else
{
/* Find the '>' character which defines the beginning of the table */
while ((chr = fgetc(read)) != '>') { }
while ((chr = fgetc(read)) != '*')
{
switch (chr)
{
/* Increment x coord */
case ' ' : ++x;
break;
/* Next line of table - reset x and decrement y coords */
case '\r' :
case '\n' : x = -4; --y;
break;
/* Character found - check that it is valid */
default : c_type = ((int) chr - 'a' + 1);
if(c_type >= 0 && c_type <= global.total_types)
{
/* Position creature if the location
* is on the grid */
if (valid_location(x,y) == TRUE)
{ grid[x][y] = c_type; }
}
++x;
break;
}
}
/* Put the '*' character back into the file buffer */
ungetc('*',read);
}
}
/**************************************************************************/
/* Read data from the SetUp file */
void read_data(int data_type)
#define NAME 0
#define INITIAL_NO 1
#define MOVE 2
#define MAX_STR 3
#define CONSUMPTION 4
#define FOOD_VALUE 5
#define ADULT 6
#define BIRTH_STR 7
#define FOOD 8
#define CHILD_STR 9
#define DECAY 10
{
int c, n;
int c_type;
char chr;
switch (data_type)
{
case NAME : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%s",type[c].name);
if (strlen(type[c].name) > 10)
{
printf("Error - Sprite name too long");
exit(NULL);
}
}
break;
case INITIAL_NO : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].initial_number);
}
break;
case MOVE : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].move);
if (type[c].move < 0)
{
printf("Error - ");
printf("Movement rate must be 0 or more");
exit(NULL);
}
}
break;
case MAX_STR : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].max_str);
if (type[c].max_str < 1)
{
printf("Error - ");
printf("Max strength must be 1 or more");
exit(NULL);
}
}
break;
case CONSUMPTION : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].consumption);
}
break;
case FOOD_VALUE : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].food_value);
}
break;
case ADULT : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].adult);
}
break;
case BIRTH_STR : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].birth_str);
}
break;
case CHILD_STR : for (c = 1; c <= global.total_types; c++)
{
fscanf(read,"%i",&type[c].child_str);
}
break;
case DECAY : for (c = 1; c <= global.total_types; c++)
{
while ((chr = fgetc(read)) == ' ') { }
c_type = (int) chr - 'a' + 1;
if (c_type > 0 && c_type <= CREATURE_TYPES)
{ type[c].decay = (char) c_type; }
}
break;
case FOOD : for (c = 1; c <= global.total_types; c++)
{
for(n = 0; n < MAX_FOOD; n++)
{
while ((chr = fgetc(read)) == ' ') { }
c_type = (int) chr - 'a' + 1;
if(c_type > 0 && c_type <= CREATURE_TYPES)
{
if(c_type != ('.' - 'a' + 1))
{type[c].food +=(int)(pow(2,c_type));}
}
}
}
break;
default : break;
}
}
/**************************************************************************/
/* Create the initial creature populations */
void create_populations(void)
{
int c_type, c, x, y;
int number = 0;
sprite_id id;
/* If random set up - fill grid */
if (global.random == TRUE)
{
for (c_type = 1; c_type <= global.total_types; c_type++)
{
for (c = 1; c <= type[c_type].initial_number; c++)
{
/* Find an empty location on the grid */
do {
x = (int) RANDOM(X_MAX - 2) + 1;
y = (int) RANDOM(Y_MAX - 2) + 1;
} while (grid[x][y] != EMPTY);
/* Put creature type onto the grid */
grid[x][y] = c_type;
}
}
}
/* Search grid and set up the initial conditions for each creature */
for (x = 1; x <= X_MAX; x++)
{
for (y = 1; y <= Y_MAX; y++)
{
if ((c_type = grid[x][y]) != EMPTY)
{
id.s.name = type[c_type].name;
++number;
++pop_tots[c_type];
++old_pop_tots[c_type];
/* Set up data */
creature[number].type = c_type;
creature[number].x = x;
creature[number].y = y;
creature[number].dx = (signed char) (RANDOM(2)) - 1;
creature[number].dy = (signed char) (RANDOM(2)) - 1;
creature[number].str=(int)(1+RANDOM(type[c_type].max_str/2));
creature[number].move_c=(int) (1 + RANDOM(type[c_type].move));
creature[number].age = (int) (1 + RANDOM(type[c_type].adult));
/* Draw sprite on the screen */
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
sprite_put_given(sprite_bk, &id, 0,
x * SCREEN_X, y * SCREEN_Y);
}
#endif
}
}
}
}
/**************************************************************************/
/* Draw graph axes */
void draw_axes(void)
{
int n;
sprite_id id;
bbc_gcol(0,GREY1);
bbc_move(ORIGIN_X,ORIGIN_Y);
bbc_drawby(0,1000 - ORIGIN_Y);
bbc_move(ORIGIN_X,ORIGIN_Y);
bbc_drawby(WIDTH,0);
bbc_colour(GREY2);
bbc_tab(63,0);
printf("Iteration");
bbc_colour(WHITE);
bbc_tab(64,1);
printf("Total");
for (n = 1; n <= global.total_types; n++)
{
bbc_colour(BLUE + n);
bbc_tab(64,n + 1);
printf("%s",type[n].name);
bbc_tab(73,n + 1);
printf("%i",pop_tots[n]);
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = type[n].name;
sprite_put_given(sprite_bk, &id, 0, 970,968 - (n * 32));
}
#endif
}
}
/**************************************************************************/
/**************************************************************************/
/* MAIN PROCESSING */
/**************************************************************************/
/* Main processing loop */
void main_loop(void)
{
int loop;
for (loop = 1; loop <= global.iterations; loop++)
{
process_creatures();
update_graph(loop);
srand(clock());
}
}
/**************************************************************************/
/* Do one iteration */
void process_creatures(void)
{
int pause;
int c;
int t;
for (c = 1; c <= MAX_CREATURES; c++)
{
if (creature[c].str != DEAD)
{
/* Get the type of creature */
t = creature[c].type;
/* Age the creature */
++creature[c].age;
/* Update movement counter */
if (++creature[c].move_c >= type[t].move && type[t].move != 0)
{ move_creature(c, t); }
/* Check for food */
feed(c, t);
/* Consume strength */
consume_strength(c, t);
/* Give birth to child ? */
birth(c, t);
}
/* Pause */
for (pause = 0; pause <= (global.wait * 100); pause++) { }
}
}
/**************************************************************************/
/* Update the graph */
void update_graph(int loop)
{
static int x = 0;
static int old_overall_total = 0;
int n;
int dead = 0;
int overall_total = 0;
/* Check for end of graph */
if (++x >= WIDTH)
{
x = 1;
bbc_gcol(0,BLACK);
bbc_rectanglefill(ORIGIN_X + 2,ORIGIN_Y + 4,WIDTH,1000 - ORIGIN_Y + 24);
}
/* Print current iteration */
bbc_colour(GREY2);
bbc_tab(73,0);
printf("%i",loop);
/* Plot graph and update population totals */
for (n = 1; n <= global.total_types; n++)
{
if (pop_tots[n] > NULL)
{
bbc_gcol(0, BLUE + n);
bbc_move(ORIGIN_X + x - 1, (int)
(ORIGIN_Y + 4 + (global.graph_scale * old_pop_tots[n])));
bbc_draw(ORIGIN_X + x, (int)
(ORIGIN_Y + 4 + (global.graph_scale * pop_tots[n])));
}
else
{
++dead;
}
bbc_colour(BLUE + n);
bbc_tab(73,n + 1);
printf("%i ",pop_tots[n]);
overall_total += pop_tots[n];
old_pop_tots[n] = pop_tots[n];
}
/* Plot overall creature total */
bbc_colour(WHITE);
bbc_tab(73,1);
printf("%i ",overall_total);
if (global.draw_overall == TRUE)
{
bbc_gcol(0,WHITE);
bbc_move(ORIGIN_X + x - 1, (int)
(ORIGIN_Y + 4 + (global.graph_scale * old_overall_total)));
bbc_draw(ORIGIN_X + x, (int)
(ORIGIN_Y + 4 + (global.graph_scale * overall_total)));
old_overall_total = overall_total;
}
/* All creatures dead - end program */
if (dead == global.total_types)
{
bbc_tab(0,29);
exit(NULL);
}
}
/**************************************************************************/
/* Move a creature */
void move_creature(int c_number, int c_type)
{
char oldx, oldy;
char newx, newy;
sprite_id id;
/* Reset movement counter */
creature[c_number].move_c = 0;
/* Choose new dx and dy ? */
if ((int) (RANDOM(10)) == 10)
{
creature[c_number].dx = (signed char) (RANDOM(2)) - 1;
creature[c_number].dy = (signed char) (RANDOM(2)) - 1;
}
/* Determine new location */
oldx = creature[c_number].x;
oldy = creature[c_number].y;
newx = oldx + creature[c_number].dx;
newy = oldy + creature[c_number].dy;
#if WRAP_AROUND == TRUE
if (newx > X_MAX) { newx = 1; }
if (newx == 0) { newx = X_MAX; }
if (newy > Y_MAX) { newy = 1; }
if (newy == 0) { newy = Y_MAX; }
#endif
#if WRAP_AROUND == FALSE
if (newx > X_MAX) { newx = X_MAX; }
if (newx == 0) { newx = 1; }
if (newy > Y_MAX) { newy = Y_MAX; }
if (newy == 0) { newy = 1; }
#endif
/* If the new location is empty then move the creature */
if (grid[newx][newy] == EMPTY)
{
/* Remove creature from old location */
grid[oldx][oldy] = EMPTY;
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = "blank";
sprite_put_given(sprite_bk, &id, 0,
oldx * SCREEN_X, oldy * SCREEN_Y);
}
#endif
/* Draw creature in the new location */
grid[newx][newy] = c_type;
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = type[c_type].name;
sprite_put_given(sprite_bk, &id, 0,
newx * SCREEN_X, newy * SCREEN_Y);
}
#endif
/* Update the creatures current coordinates */
creature[c_number].x = newx;
creature[c_number].y = newy;
}
}
/**************************************************************************/
/* Creature consumes strength */
void consume_strength(int c_number, int c_type)
{
int dir;
int decay_number;
int decay_type;
int x, y;
int dx,dy;
sprite_id id;
/* Consume strength. If the strength falls to zero or less
* the kill the creature */
if ((creature[c_number].str -= type[c_type].consumption) <= 0)
{
x = creature[c_number].x;
y = creature[c_number].y;
/* Kill the creature */
creature[c_number].str = DEAD;
--pop_tots[c_type];
grid[x][y] = EMPTY;
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = "blank";
sprite_put_given(sprite_bk, &id, 0, x * SCREEN_X, y * SCREEN_Y);
}
#endif
/* Does the death of this creature form any decay products ? */
decay_type = type[c_type].decay;
if (decay_type != NULL)
{
for (dir = 0; dir < DIRECTIONS; dir++)
{
dx = x + loc_offset[dir].dx;
dy = y + loc_offset[dir].dy;
/* Is the cell location valid ? */
if (valid_location(dx,dy) == TRUE)
{
/* Is cell empty ? */
if (grid[dx][dy] == EMPTY)
{
/* Resurrect a dead creature (except if FAIL) */
if ((decay_number = find_free_creature()) != FAIL)
{
/* Create decay creature */
creature[decay_number].str =
1 + (int) RANDOM(type[decay_type].max_str);
creature[decay_number].age = 1;
creature[decay_number].type = decay_type;
creature[decay_number].move_c = 0;
creature[decay_number].x = dx;
creature[decay_number].y = dy;
creature[decay_number].dx =
(signed char) (RANDOM(2)) - 1;
creature[decay_number].dy =
(signed char) (RANDOM(2)) - 1;
++pop_tots[decay_type];
/* Fill grid and draw decay creature on screen */
grid[dx][dy] = decay_type;
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = type[decay_type].name;
sprite_put_given(sprite_bk, &id, 0,
dx * SCREEN_X, dy * SCREEN_Y);
}
#endif
}
}
}
}
}
}
}
/**************************************************************************/
/* Check surrounding locations for possible food */
void feed(int c_number, int c_type)
{
int n;
int x, y;
int dx,dy;
int nbour_type;
int nbour_number;
sprite_id id;
x = creature[c_number].x;
y = creature[c_number].y;
for (n = 0; n < DIRECTIONS; n++)
{
dx = x + loc_offset[n].dx;
dy = y + loc_offset[n].dy;
/* Check that the neighbouring cell is on grid */
if (valid_location(dx,dy) == TRUE)
{
/* Get creature type in the cell */
nbour_type = grid[dx][dy];
if (nbour_type != EMPTY)
{
/* Does this creature eat neighbouring type ? */
if ((type[c_type].food & (int) (pow(2,nbour_type))) != NULL)
{
/* Find the neighbour's number */
if ((nbour_number = find_creature_at(dx,dy)) != FAIL)
{
/* Eat the neighbour */
creature[c_number].str += type[nbour_type].food_value;
if (creature[c_number].str > type[c_type].max_str)
{ creature[c_number].str = type[c_type].max_str; }
creature[nbour_number].str = DEAD;
--pop_tots[nbour_type];
/* Remove neighbour from grid and screen */
grid[dx][dy] = EMPTY;
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = "blank";
sprite_put_given(sprite_bk, &id, 0,
dx * SCREEN_X, dy * SCREEN_Y);
}
#endif
}
}
}
}
}
}
/**************************************************************************/
/* Give birth to a child */
void birth(int c_number, int c_type)
{
int dir;
int child_number;
int x, y;
sprite_id id;
/* Can the creature have children and is the creature an adult ? */
if (type[c_type].adult > 0 && creature[c_number].age >= type[c_type].adult)
{
/* Has the creature enough strength ? */
if (creature[c_number].str >= type[c_type].birth_str)
{
/* Choose and random neighbouring cell - check that it is valid */
dir = (int) RANDOM(DIRECTIONS - 1);
x = creature[c_number].x + loc_offset[dir].dx;
y = creature[c_number].y + loc_offset[dir].dy;
if (valid_location(x,y) == TRUE)
{
/* Check that cell is empty */
if (grid[x][y] == EMPTY)
{
/* Resurrect a dead creature (except if FAIL) */
if ((child_number = find_free_creature()) != FAIL)
{
/* Create child */
creature[child_number].str = creature[c_number].str *
type[c_type].child_str / 100;
creature[child_number].age = 1;
creature[child_number].type = c_type;
creature[child_number].move_c = 0;
creature[child_number].x = x;
creature[child_number].y = y;
creature[child_number].dx=(signed char) (RANDOM(2)) - 1;
creature[child_number].dy=(signed char) (RANDOM(2)) - 1;
++pop_tots[c_type];
/* Adjust parents data */
creature[c_number].str = creature[c_number].str *
(100 - type[c_type].child_str) / 100;
/* Fill grid and draw child creature on screen */
grid[x][y] = c_type;
#if GRAPHICS == TRUE
if (global.draw_creatures == TRUE)
{
id.s.name = type[c_type].name;
sprite_put_given(sprite_bk, &id, 0,
x * SCREEN_X, y * SCREEN_Y);
}
#endif
}
}
}
}
}
}
/**************************************************************************/
/**************************************************************************/
/* GENERAL ROUTINES */
/**************************************************************************/
/* Check that location is valid ie on the grid */
BOOL valid_location(char x, char y)
{
if (x > X_MAX || x < 1 || y > Y_MAX || y < 1) { return(FALSE); }
return(TRUE);
}
/**************************************************************************/
/* Find the creature number at a given location or return FAIL
* if not found */
int find_creature_at(char x, char y)
{
int n;
for (n = 1; n <= MAX_CREATURES; n++)
{
if (creature[n].str != DEAD)
{
if (creature[n].x == x && creature[n].y == y)
{ return(n); }
}
}
return(FAIL);
}
/**************************************************************************/
/* Return a dead creature for reuse or FAIL if not available */
int find_free_creature(void)
{
int n;
for (n = 1; n <= MAX_CREATURES; n++)
{
if (creature[n].str == DEAD) { return(n); }
}
return(FAIL);
}
/**************************************************************************/
/* Main procedure */
int main()
{
initialise();
if (load_file() == FALSE) { return(NULL); }
create_populations();
draw_axes();
main_loop();
bbc_tab(0,29);
return(NULL);
}
/**************************************************************************/